package com.caissa.framework.starter.autoconfigure.annotation;

import com.dianping.cat.Cat;
import com.dianping.cat.message.Transaction;
import com.dianping.cat.message.internal.NullMessage;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.cloud.openfeign.FeignClient;

import java.lang.reflect.Method;

import static com.caissa.framework.starter.autoconfigure.common.CatHttpConstants.CAT_RPC_CALL;
import static com.caissa.framework.starter.autoconfigure.common.CatHttpConstants.CAT_RPC_CALL_SERVER_APPID;

@Aspect
public class CatAopAdvise {

    @Around("@annotation(com.base.framework.starter.autoconfigure.annotation.CatAop) ")
    public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable{
        String remoteAppName = null;
        Transaction t;
        try {
            MethodSignature joinPointObject = (MethodSignature) pjp.getSignature();
            Method method = joinPointObject.getMethod();

            Class curFeignClass = joinPointObject.getDeclaringType();
            Class<FeignClient> feignClientAnnoClass = FeignClient.class;

            String type = getTagName(joinPointObject);
            remoteAppName = null;

            if (curFeignClass.isAnnotationPresent(feignClientAnnoClass)) {
                FeignClient annotation = (FeignClient) curFeignClass.getAnnotation(feignClientAnnoClass);
                type = CAT_RPC_CALL;
                if (annotation != null && annotation.name() != null) {
                    remoteAppName = annotation.name();
                }
            }
            t = Cat.newTransaction(type, method.getName());
        } catch (Exception e) {
            e.printStackTrace();
            t = NullMessage.TRANSACTION;
        }

        try {
            if (remoteAppName != null) {
                //服务端Ip
                //Cat.logEvent("Call.server",remoteIp);
                Cat.logEvent(CAT_RPC_CALL_SERVER_APPID,remoteAppName);
            }

            Object obj = pjp.proceed();

            t.setSuccessStatus();
            return obj;
        } catch (Throwable e) {
            t.setStatus(e);
            //ExceptionTransformer.ifThrowCheckedException(e);
            //throw new RuntimeException("", e);
            throw e;
        } finally {
            t.complete();
        }
    }

    private String getTagName(MethodSignature joinPointObject) {
        try {
            String classname = joinPointObject.getMethod().getDeclaringClass().getName();

            if (classname == null) {
                return "Method";
            } else if (classname.toLowerCase().indexOf("controller") != -1) {
                return "Controller";
            }else if (classname.toLowerCase().indexOf("redis") != -1) {
                return "Redis";
            }else if (classname.toLowerCase().indexOf("job") != -1) {
                return "Job";
            }
        } catch (Throwable e) {
            //ignore
        }
        return "Method";
    }
}